package casbin_plugin

import (
	"gitee.com/kristas/booting-go/framework/core/log"
	"gitee.com/kristas/booting-go/framework/core/statement/types"
	"gitee.com/kristas/booting-go/framework/security"
	"gitee.com/kristas/booting-go/framework/web"
	"net/http"
)

type CasbinFilter struct {
	types.Filter `order:"2" pattern:"/*"`
	Cas          *security.Casbin `wire:""`
	getRole      func(r *http.Request) string
	Log          log.Logger `wire:""`
}

func NewFilter(getRoleFunc func(r *http.Request) string) *CasbinFilter {
	return &CasbinFilter{getRole: getRoleFunc}
}

func (c *CasbinFilter) DoFilter(w http.ResponseWriter, r *http.Request, chain web.FilterChain) error {
	obj := r.RequestURI
	act := r.Method
	sub := c.getRole(r)

	if enforce, err := c.Cas.GetEnforcer().Enforce(sub, obj, act); enforce {
		return chain.DoFilter(w, r)
	} else {
		if err != nil {
			return err
		}
		c.Log.Info("Unauthorized for: sub(%s), obj(%s), act(%s)", sub, obj, act)
		w.WriteHeader(http.StatusUnauthorized)
		return err
	}
}
